﻿#include "DefaultMeshFactory.h"

#include "Mesh.h"

static float GCubePosUVVertices[] = {
	// Back face
	-0.5f, -0.5f, -0.5f,  0.0f, 0.0f, // Bottom-left
	0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right
	0.5f, -0.5f, -0.5f,  1.0f, 0.0f, // bottom-right         
	0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right
	-0.5f, -0.5f, -0.5f,  0.0f, 0.0f, // bottom-left
	-0.5f,  0.5f, -0.5f,  0.0f, 1.0f, // top-left
									  // Front face
									  -0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left
									  0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
									  0.5f,  0.5f,  0.5f,  1.0f, 1.0f, // top-right
									  0.5f,  0.5f,  0.5f,  1.0f, 1.0f, // top-right
									  -0.5f,  0.5f,  0.5f,  0.0f, 1.0f, // top-left
									  -0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left
																		// Left face
																		-0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-right
																		-0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-left
																		-0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-left
																		-0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-left
																		-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-right
																		-0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-right
																										  // Right face
																										  0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-left
																										  0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-right
																										  0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right         
																										  0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-right
																										  0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-left
																										  0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left     
																																		   // Bottom face
																																		   -0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // top-right
																																		   0.5f, -0.5f, -0.5f,  1.0f, 1.0f, // top-left
																																		   0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-left
																																		   0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-left
																																		   -0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-right
																																		   -0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // top-right

																																		   -0.5f,  0.5f, -0.5f,  0.0f, 1.0f, // top-left
																																		   0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
																																		   0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right     
																																		   0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
																																		   -0.5f,  0.5f, -0.5f,  0.0f, 1.0f, // top-left
																																		   -0.5f,  0.5f,  0.5f,  0.0f, 0.0f  // bottom-left        
};
static std::vector<FVertexInfo> GStaticVertices = {
	// positions          // normals           // texture coords
	FVertexInfo{glm::vec3(-0.5f, -0.5f, -0.5f),  glm::vec3(0.0f,  0.0f, -1.0f), glm::vec2(0.0f, 0.0f)},
	FVertexInfo{glm::vec3(0.5f, -0.5f, -0.5f),  glm::vec3(0.0f,  0.0f, -1.0f),  glm::vec2(1.0f, 0.0f)},
	FVertexInfo{glm::vec3(0.5f,  0.5f, -0.5f),  glm::vec3(0.0f,  0.0f, -1.0f),  glm::vec2(1.0f, 1.0f)},
	FVertexInfo{glm::vec3(0.5f,  0.5f, -0.5f),  glm::vec3(0.0f,  0.0f, -1.0f),  glm::vec2(1.0f, 1.0f)},
	FVertexInfo{glm::vec3(-0.5f,  0.5f, -0.5f),  glm::vec3(0.0f,  0.0f, -1.0f),  glm::vec2(0.0f, 1.0f)},
	FVertexInfo{glm::vec3(-0.5f, -0.5f, -0.5f),  glm::vec3(0.0f,  0.0f, -1.0f),  glm::vec2(0.0f, 0.0f)},

	FVertexInfo{glm::vec3(-0.5f, -0.5f,  0.5f),  glm::vec3(0.0f,  0.0f, 1.0f),   glm::vec2(0.0f, 0.0f)},
	FVertexInfo{glm::vec3(0.5f, -0.5f,  0.5f),  glm::vec3(0.0f,  0.0f, 1.0f),   glm::vec2(1.0f, 0.0f)},
	FVertexInfo{glm::vec3(0.5f,  0.5f,  0.5f),  glm::vec3(0.0f,  0.0f, 1.0f),   glm::vec2(1.0f, 1.0f)},
	FVertexInfo{glm::vec3(0.5f,  0.5f,  0.5f),  glm::vec3(0.0f,  0.0f, 1.0f),   glm::vec2(1.0f, 1.0f)},
	FVertexInfo{glm::vec3(-0.5f,  0.5f,  0.5f),  glm::vec3(0.0f,  0.0f, 1.0f),   glm::vec2(0.0f, 1.0f)},
	FVertexInfo{glm::vec3(-0.5f, -0.5f,  0.5f),  glm::vec3(0.0f,  0.0f, 1.0f),   glm::vec2(0.0f, 0.0f)},

	FVertexInfo{glm::vec3(-0.5f,  0.5f,  0.5f), -glm::vec3(1.0f,  0.0f,  0.0f),  glm::vec2(1.0f, 0.0f)},
	FVertexInfo{glm::vec3(-0.5f,  0.5f, -0.5f), -glm::vec3(1.0f,  0.0f,  0.0f),  glm::vec2(1.0f, 1.0f)},
	FVertexInfo{glm::vec3(-0.5f, -0.5f, -0.5f), -glm::vec3(1.0f,  0.0f,  0.0f),  glm::vec2(0.0f, 1.0f)},
	FVertexInfo{glm::vec3(-0.5f, -0.5f, -0.5f), -glm::vec3(1.0f,  0.0f,  0.0f),  glm::vec2(0.0f, 1.0f)},
	FVertexInfo{glm::vec3(-0.5f, -0.5f,  0.5f), -glm::vec3(1.0f,  0.0f,  0.0f), glm::vec2(0.0f, 0.0f)},
	FVertexInfo{glm::vec3(-0.5f,  0.5f,  0.5f), -glm::vec3(1.0f,  0.0f,  0.0f),  glm::vec2(1.0f, 0.0f)},

	FVertexInfo{glm::vec3(0.5f,  0.5f,  0.5f),  glm::vec3(1.0f,  0.0f,  0.0f),  glm::vec2(1.0f, 0.0f)},
	FVertexInfo{glm::vec3(0.5f,  0.5f, -0.5f),  glm::vec3(1.0f,  0.0f,  0.0f),  glm::vec2(1.0f, 1.0f)},
	FVertexInfo{glm::vec3(0.5f, -0.5f, -0.5f),  glm::vec3(1.0f,  0.0f,  0.0f),  glm::vec2(0.0f, 1.0f)},
	FVertexInfo{glm::vec3(0.5f, -0.5f, -0.5f),  glm::vec3(1.0f,  0.0f,  0.0f),  glm::vec2(0.0f, 1.0f)},
	FVertexInfo{glm::vec3(0.5f, -0.5f,  0.5f),  glm::vec3(1.0f,  0.0f,  0.0f),  glm::vec2(0.0f, 0.0f)},
	FVertexInfo{glm::vec3(0.5f,  0.5f,  0.5f),  glm::vec3(1.0f,  0.0f,  0.0f),  glm::vec2(1.0f, 0.0f)},

	FVertexInfo{glm::vec3(-0.5f, -0.5f, -0.5f),  glm::vec3(0.0f, -1.0f,  0.0f),  glm::vec2(0.0f, 1.0f)},
	FVertexInfo{glm::vec3(0.5f, -0.5f, -0.5f),  glm::vec3(0.0f, -1.0f,  0.0f),  glm::vec2(1.0f, 1.0f)},
	FVertexInfo{glm::vec3(0.5f, -0.5f,  0.5f),  glm::vec3(0.0f, -1.0f,  0.0f),  glm::vec2(1.0f, 0.0f)},
	FVertexInfo{glm::vec3(0.5f, -0.5f,  0.5f),  glm::vec3(0.0f, -1.0f,  0.0f),  glm::vec2(1.0f, 0.0f)},
	FVertexInfo{glm::vec3(-0.5f, -0.5f,  0.5f),  glm::vec3(0.0f, -1.0f,  0.0f),  glm::vec2(0.0f, 0.0f)},
	FVertexInfo{glm::vec3(-0.5f, -0.5f, -0.5f),  glm::vec3(0.0f, -1.0f,  0.0f),  glm::vec2(0.0f, 1.0f)},

	FVertexInfo{glm::vec3(-0.5f,  0.5f, -0.5f),  glm::vec3(0.0f,  1.0f,  0.0f),  glm::vec2(0.0f, 1.0f)},
	FVertexInfo{glm::vec3(0.5f,  0.5f, -0.5f),  glm::vec3(0.0f,  1.0f,  0.0f),  glm::vec2(1.0f, 1.0f)},
	FVertexInfo{glm::vec3(0.5f,  0.5f,  0.5f),  glm::vec3(0.0f,  1.0f,  0.0f),  glm::vec2(1.0f, 0.0f)},
	FVertexInfo{glm::vec3(0.5f,  0.5f,  0.5f),  glm::vec3(0.0f,  1.0f,  0.0f),  glm::vec2(1.0f, 0.0f)},
	FVertexInfo{glm::vec3(-0.5f,  0.5f,  0.5f),  glm::vec3(0.0f,  1.0f,  0.0f),  glm::vec2(0.0f, 0.0f)},
	FVertexInfo{glm::vec3(-0.5f,  0.5f, -0.5f),  glm::vec3(0.0f,  1.0f,  0.0f),  glm::vec2(0.0f, 1.0f)}
};

std::shared_ptr<FMesh> FDefaultMeshFactory::CreateCube(const ECubeVertexType Type)
{
	auto P = std::make_shared<FMesh>();
	if (Type == ECubeVertexType::PosNormalUV)
	{
		P->InitVertex(GStaticVertices);
	}
	else if (Type == ECubeVertexType::PosUV)
	{
		std::vector<FVertexInfo> BoxVertex;

		for (int32_t Index = 0; Index < 180;)
		{
			BoxVertex.push_back(
				FVertexInfo
				{
					glm::vec3(GCubePosUVVertices[Index + 0], GCubePosUVVertices[Index + 1],GCubePosUVVertices[Index + 2]),
					glm::vec3(),
					glm::vec2(GCubePosUVVertices[Index + 3], GCubePosUVVertices[Index + 4])
				}
			);
			Index += 5;
		}

		P->InitVertex(BoxVertex);
	}

	return P;
}


static float GQuadVertices[] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
								  // positions   // texCoords
	-1.0f,  1.0f, 0.f, 0.0f, 1.0f,
	-1.0f, -1.0f, 0.f, 0.0f, 0.0f,
	1.0f, -1.0f,  0.f, 1.0f, 0.0f,

	-1.0f,  1.0f, 0.f, 0.0f, 1.0f,
	1.0f, -1.0f,  0.f, 1.0f, 0.0f,
	1.0f,  1.0f,  0.f, 1.0f, 1.0f
};


std::shared_ptr<FMesh> FDefaultMeshFactory::CreateQuad()
{
	auto P = std::make_shared<FMesh>();

	std::vector<FVertexInfo> VertexArr;
	for (int32_t Index = 0; Index < 30;)
	{
		VertexArr.push_back(
			FVertexInfo
			{
				glm::vec3(GQuadVertices[Index + 0], GQuadVertices[Index + 1],GQuadVertices[Index + 2]),
				glm::vec3(),
				glm::vec2(GQuadVertices[Index + 3], GQuadVertices[Index + 4])
			}
		);
		Index += 5;
	}
	P->InitVertex(VertexArr);

	return P;
}
